﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace BadHabit.Factory.Windows {

    /// <summary>
    /// Interaction logic for TeamAllocation.xaml
    /// </summary>
    public partial class TeamAllocation : BadHabit.WPFTools.ShapedWindow {

        System.Data.DataSet dsTasks = new System.Data.DataSet();

        private List<string> membersWorking = new List<string>();
        private List<string> membersWithTasks = new List<string>();
        private Data.TeamDataSet membersAtMyProjects = new BadHabit.Factory.Data.TeamDataSet();
        
        private WPFTools.DelayFilter delayFilter;


        public TeamAllocation() {
            InitializeComponent();
            delayFilter = new WPFTools.DelayFilter(1, ApplyFilter);
        }

        public TeamAllocation(int projectNumber) {
            InitializeComponent();            
            delayFilter = new WPFTools.DelayFilter(1, ApplyFilter);
            searchTextBox.Text = projectNumber.ToString();
        }


        private void ShapedWindow_Loaded(object sender, RoutedEventArgs e) {

            
            Load();
            
            searchTextBox.Focus();
            
            
        }

        private void Load() {
            try {
                LoadTasks();
                BindTeamMembers();

                SetMembersWorking();
                SetMembersWithTasks();

                SetMembersInMyProjects();


                CreateScaleVisualBrush();
            } catch (Exception ex) {
                Windows.Error.ShowError(ex, "Sory, could not read member´s tasks.");
            }

                
        }
        private Data.TeamDataSet teamDataSet;

        private void BindTeamMembers() {

            teamDataSet = new BadHabit.Factory.Data.TeamDataSet();

            teamDataSet.Merge(Client.TeamMemberDataSet);
            teamDataSet.Merge(Client.Service.RetriveAllMemberAllocation());

            CreateAllocationColumns();

            System.Data.DataView members = Client.TeamMemberDataSet.DefaultViewManager.CreateDataView(teamDataSet.Member);
            members.Sort = "NickName";
            members.RowFilter = "Disable<>1 or Disable is null";
            ListCollectionView view = new ListCollectionView(members);

            
            view.Filter = IsInFilter;
            memberListView.ItemsSource = view;
        }

        private void CreateAllocationColumns() {
            if(!teamDataSet.Member.Columns.Contains("ProjectCount"))
                teamDataSet.Member.Columns.Add("ProjectCount", typeof(int));
            if (!teamDataSet.Member.Columns.Contains("AvailableAt"))
                teamDataSet.Member.Columns.Add("AvailableAt", typeof(DateTime));

            foreach (Data.TeamDataSet.MemberAllocationRow allocationRow in teamDataSet.MemberAllocation) {
                Data.TeamDataSet.MemberRow memberRow = teamDataSet.Member.FindByMemberId(allocationRow.MemberId);
                if (memberRow != null) {
                    memberRow["ProjectCount"] = allocationRow.ProjectCount;
                    memberRow["AvailableAt"] = allocationRow.AvailableAt;
                }
            }
        }

        private double CalcMaxTimeScale() {
            double maxEffort = 0;
            foreach (Data.TeamDataSet.MemberRow member in Client.TeamMemberDataSet.Member) {
                object o = dsTasks.Tables["TaskResume"].Compute("SUM(PlannedEffort)", "TaskAssignee='" + member.MemberId + "'");
                double effort;
                Double.TryParse(o.ToString(), out effort);

                if (effort > maxEffort)
                    maxEffort = effort;

            }            
            return maxEffort;
        }
   

        private DateTime NextValidTimeScale(DateTime time) {

            DateTime nextTime;

            // if is not a work day, move to the next
            if (!Data.ProjectDataSet.IsWorkDay(time)) {
                nextTime = time.AddDays(1);
                return NextValidTimeScale(new DateTime(nextTime.Year, nextTime.Month, nextTime.Day, 9, 0, 0));
            }

            // if is earlier then 9oclock, move to 9
            if (time.Hour < 9)
                return NextValidTimeScale(new DateTime(time.Year, time.Month, time.Day, 9, 0, 0));

            // if is after the 6oclock
            if (time.Hour > 18) {
                nextTime = time.AddDays(1);
                return NextValidTimeScale(new DateTime(nextTime.Year, nextTime.Month, nextTime.Day, 9, 0, 0));
            }

            if (time.Hour == 13)
                return time.AddHours(1);

            return time;

        }

        /// <summary>
        /// Verifies if a given task is or not at the filter.
        /// </summary>
        /// <param name="obj">Task</param>
        /// <returns>True if its on the filter</returns>
        internal bool IsInFilter(object obj) {
            System.Data.DataRowView member = obj as System.Data.DataRowView;
            if (obj == null)
                return false;

            if (freeAtDatePicker.SelectedDate != null) {                
                if(!DBNull.Value.Equals(member["AvailableAt"]))
                    if ((DateTime)member["AvailableAt"] > freeAtDatePicker.SelectedDate)
                        return false;
            }

            if (idleButton.IsChecked == true) {
                if (membersWorking.Contains(member["MemberId"].ToString()))
                    return false;                
            }

            if (availableButton.IsChecked == true)
                if (membersWithTasks.Contains(member["MemberId"].ToString()))
                    return false;

            if (myProjectButton.IsChecked == true)
                if(membersAtMyProjects.Member.FindByMemberId(member["MemberId"].ToString())==null)
                    return false;
                
            if (member["NickName"].ToString().ToLower().Contains(searchTextBox.Text.ToLower()))
                return true;

            if (member["DefaultUnitName"].ToString().ToLower().Contains(searchTextBox.Text.ToLower()))
                return true;

            if( MembersAtProject(searchTextBox.Text).Contains(member["MemberId"].ToString()))
                return true;

            return false;
        }

        private void SetMembersWorking() {            
            System.Data.DataRow[] tasks = dsTasks.Tables["TaskResume"].Select("IsWorking=1");            
            foreach (System.Data.DataRow task in tasks)
                if (!membersWorking.Contains(task["TaskAssignee"].ToString()))
                    membersWorking.Add(task["TaskAssignee"].ToString());
        }

        private void SetMembersWithTasks() {            
            System.Data.DataRow[] tasks = dsTasks.Tables["TaskResume"].Select("");            
            foreach (System.Data.DataRow task in tasks)
                if (!membersWithTasks.Contains(task["TaskAssignee"].ToString()))
                    membersWithTasks.Add(task["TaskAssignee"].ToString());             
        }

        private void SetMembersInMyProjects() {            
            try {
                membersAtMyProjects.Merge(Client.Service.RetriveMembersAtSameProject(Client.User.Identity.Name));
            }catch(Exception ex) {
                Windows.Error.ShowError(ex, "Sorry, could not retrive members working at your projects.");                
            }
            
        }


        private List<string> MembersAtProject(string text) {

            string filter = "ProjectName Like '%" + text + "%' Or ClientName LIKE '%" + text + "%'";
            int projectNumber;
            if (Int32.TryParse(text, out projectNumber)) {
                filter = filter + " OR ProjectNumber = " + projectNumber;
            }

            System.Data.DataRow[] tasks = dsTasks.Tables["TaskResume"].Select(filter);

            List<string> membersIdAtProject = new List<string>();
            foreach (System.Data.DataRow task in tasks) 
                if (!membersIdAtProject.Contains(task["TaskAssignee"].ToString()))
                    membersIdAtProject.Add(task["TaskAssignee"].ToString());
            
            return membersIdAtProject;
        }


        private void LoadTasks() {            
            dsTasks.Merge(Client.Service.RetriveOpenedTasks());                                        
        }

        private void CreateScaleVisualBrush() {
            VisualBrush v = Resources["ScaleVisualBrush"] as VisualBrush;
            if (v == null)
                return;

            Canvas scaleCanvas = v.Visual as Canvas;

            double X2 = Client.TeamMemberDataSet.Member.Count * 100;
            Line r1 = new Line();
            r1.X1 = 1;
            r1.X2 = X2;
            r1.Y1 = 1;
            r1.Y2 = 1;
            r1.Stroke = Brushes.White;
            scaleCanvas.Children.Add(r1);
            
            double h = 120;
            DateTime time = NextValidTimeScale(DateTime.Now);            
            DateTime endTime = DateTime.Now.AddDays(CalcMaxTimeScale()/5);

            while (time < endTime) {

                string text = time.Hour + " hr";
                Brush color = Brushes.Gray;

                Line r = new Line();
                if (time.Hour != 9) {
                    r.StrokeDashArray = new DoubleCollection(new double[] { 2, 2 });                    
                } else {
                    color = (Brush) Client.CurrentClient.Resources["DarkBrush"];
                    text = text + ", " + time.ToShortDateString();                    
                }

                r.X1 = 0;
                r.X2 = X2;
                r.Y1 = h;
                r.Y2 = h;
                r.Stroke = color;
                scaleCanvas.Children.Add(r);

                TextBlock t = new TextBlock();
                t.Text = text;
                t.SetValue(Canvas.TopProperty, h+1);
                t.SetValue(Canvas.LeftProperty, 2.0);
                t.Foreground = color;
                scaleCanvas.Children.Add(t);

                h = h + 25;
                time = NextValidTimeScale(time.AddHours(1));

            }

            
        
        }

        private void searchTextBox_SelectionChanged(object sender, RoutedEventArgs e) {
            delayFilter.StartFilter();
        }

        private void taskListView_Loaded(object sender, RoutedEventArgs e) {
            ListBox list = sender as ListBox;
            if (list == null)
                return;

            Data.TeamDataSet.MemberRow member = Helper.GetRowFromRowView<Data.TeamDataSet.MemberRow>(list.DataContext);
            if (member == null)
                return;
           
            System.Data.DataView taskView = dsTasks.DefaultViewManager.CreateDataView(dsTasks.Tables["TaskResume"]);
            taskView.RowFilter = "TaskAssignee='" + member.MemberId + "'";
            taskView.Sort = "IsWorking DESC, Status DESC, PlannedFinish";
            list.ItemsSource = taskView;
        }


        private void idleButton_Click(object sender, RoutedEventArgs e) {
            ApplyFilter();
        }


        private void ApplyFilter() {
            ListCollectionView view = memberListView.ItemsSource as ListCollectionView;
            if (view == null)
                return;
            view.Refresh();
        }

        private void refreshtButton_Click(object sender, RoutedEventArgs e) {
            Load();
        }

        private void freeAtDatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e) {
            ApplyFilter();
        }



    }
}
